"use strict";

$(() => {
    function replace_to_loading(el)
    {
        el = $(el);
        var loading = $('<span>').append($('<span>', { 'class': 'fa fa-cog fa-spin' }));
        el.replaceWith(loading);
        var resume = () => loading.replaceWith(el);
        return resume;
    }

    function api(url, args)
    {
        if (args instanceof HTMLFormElement) args = new FormData(args);
        var process_data = !(args instanceof FormData);
        var content_type = process_data ? undefined : false;

        var result = $.Deferred();
        $.post({
            url,
            data: args,
            processData: process_data,
            contentType: content_type,
            cache: false,
        })
            .fail(() => result.reject("连接到服务器失败"))
            .done(data => {
                if (data.error === 'login' || data.error === 'denied')
                    return reload("throw=" + data.error)();
                if (data.error != null) return result.reject(data.error.replace(/^bad request:\s*/, ''));
                if (!(data instanceof Object)) return result.reject(data);
                result.resolve(data.result);
            });
        return result;
    }

    function camel_case_to_dash(x)
    {
        return x.replace(/[A-Z]/g, m => "-" + m.toLowerCase());
    }

    function button_api(ev, show_err)
    {
        ev.preventDefault();
        if (show_err == null) show_err = err => alert(err);

        var target = ev.currentTarget;
        var resume = replace_to_loading(target);
        var data = $(target).data();

        var url = data.api;
        if (url == null) return;

        var args = {};
        var arg_prefix = "api-";
        for (var arg in data) {
            var dash_arg = camel_case_to_dash(arg);
            if (dash_arg.startsWith(arg_prefix))
                args[dash_arg.substr(arg_prefix.length)] = data[arg];
        }

        var result = api(url, args).fail(err => {
            show_err(err);
            resume();
        });

        var redirect = data.redirect;
        result = result.done(redirect == null ? reload() : goto(data.redirect))

        return result;
    }

    function form_api(form)
    {
        form = $(form);
        var url = form.attr('action');
        var error = $('.form-error', form);
        var submit = $('.form-controls > button:last-child', form);
        var resume = replace_to_loading(submit);
        var redirect = form.data('redirect');

        return api(url, form[0])
            .fail(err => {
                error.text(err);
                resume();
            })
            .done(redirect == null ? reload() : goto(redirect));
    }

    function reload(search)
    {
        var parser = document.createElement('a');
        parser.href = location.href;

        if (search == null && location.search.search(/[?&]throw=/) === 0)
            search = "";
        if (search != null) parser.search = search;

        return goto(parser.href);
    }

    function goto(path)
    {
        var parser = document.createElement('a');
        parser.href = path;

        if (parser.origin !== location.origin) return () => location.href = path;
        if (parser.pathname !== location.pathname) return () => location.href = path;
        if (parser.hash === "") return () => location.href = path;
        return () => {
            location.hash = parser.hash;
            location.reload();
        }
    }

    function validate_pair(slave)
    {
        var form = $(slave.form);
        slave = $(slave);

        var master = slave.data('same-value');
        if (master == null) return;
        master = $(`input[name=${master}]`, form)[0];
        if (master == null) return;
        master = $(master);

        var validity = slave.val() === master.val();
        validity = validity ? "" : "输入不一致";
        console.log(validity);
        slave[0].setCustomValidity(validity);
    }

    function validate_pair_master(master)
    {
        var form = $(master.form);
        var m = $(master);

        var slaves = $('input[data-same-value]', form)
            .filter((_, slave) => $(slave).data('same-value') === master.name);

        slaves.each((_, slave) => {
            slave = $(slave);
            var validity = slave.val() === m.val();
            validity = validity ? "" : "输入不一致";
            console.log(validity);
            slave[0].setCustomValidity(validity);
        })
    }

    $(document).on('change', 'form input[data-same-value]', ev => validate_pair(ev.currentTarget));
    $(document).on('input', 'form input[data-same-value]', ev => validate_pair(ev.currentTarget));
    $(document).on('change', 'form input', ev => validate_pair_master(ev.currentTarget));
    $(document).on('input', 'form input', ev => validate_pair_master(ev.currentTarget));

    $(document).on('submit', 'form', ev => {
        ev.preventDefault();
        var form = ev.currentTarget;
        form_api(form);
    });

    $(document).on('click', 'a[data-api]', ev => {
        button_api(ev);
    });

    // focus on first input of a form, if there is one
    $('.content-wrapper > form > *:first-child').focus();

    // highlight menu item of current page
    $(`.menu-split > aside > a[href="${location.pathname}"]`).addClass('current-page');

    // button with data-href will redirect
    $('button[data-href]').click(ev => {
        ev.preventDefault();
        var href = $(ev.target).data('href');
        goto(href)();
    });
});

